# -*- coding:utf-8 -*-

from Queue import Queue
from cn.pigersing.PyShare.Event import *
from cn.pigersing.PyShare.PyShareEvents import *
from cn.pigersing.PyShare.Services.ServiceBase import *
from cn.pigersing.PyShare.Services.ServiceExceptions import *
from cn.pigersing.PyShare.utils.LogPrint import get_logger
from cn.pigersing.PyShare.utils.Xml2Obj import Element, Xml2Obj
import threading
import time

logger = get_logger('Chat')
# don't display the debug information
logger.setLevel(20)

class InstMessage(Element):
    
    class Msg(Element):
        ''' 
        inner class, defines the message content,
        which may be in future text with a structure
        '''
        
        def __init__(self, msg):
            # construct a element instance, and convert message to utf-8 
            # then use base64 to encoding it
            Element.__init__(self, 'msg')
            self.setData(msg)
    
    def __init__(self, msg, sender, to='*', MsgClass=Msg):
        
        self.MsgClass = MsgClass
        Element.__init__(self, 'InstMessage', children=[self.MsgClass(msg)])
        self.to = to
        self.sender = sender        
    
    def sender():#@NoSelf 
        def fget(self):
            return self.getAttribute('sender')
           
        def fset(self, value):
            self.setAttribute('sender', value)
           
        return locals()
       
    sender = property(**sender())
    
    def to():#@NoSelf
        def fget(self):
            return self.getAttribute('to')
           
        def fset(self, value):
            self.setAttribute('to', value)
           
        return locals()
       
    to = property(**to())    
    
    def msg():#@NoSelf
        def fget(self):
            msg = self._children[0].getData() 
            return msg
           
        def fset(self, value):
            self._children = [self.MsgClass(value)]
                      
        return locals()
           
    msg = property(**msg())
    
    def time_span(): #@NoSelf
        doc = """ received time """ #@UnusedVariable
       
        def fget(self):
            return self._time_span
           
        def fset(self, value):
            self._time_span = value
           
        return locals()
       
    time_span = property(**time_span())
    
        
    @staticmethod
    def from_xml_string(src, MsgClass=Msg):
        element = Element.from_xml_string(src)
        msg = element.getElements('msg')[0].getData()
        return InstMessage(msg,
                       element.getAttribute('sender'),
                       element.getAttribute('to'),
                       MsgClass)
        
        
class Chatting(ServiceWithEvent): 

    ''' chatting service '''
    
    def __init__(self):
        super(Chatting, self).__init__('chat')
        
    @expose
    def receive(self, message):
        ''' receive a message from other peer'''
        self.dispatch(message)
        # always return success
        return SUCCESS_BASE
    
    @expose
    def get_nickname(self):
        ''' get a nick name of current server'''
        return self.root.server.nickname
        

class ChatClientBase(PyShareEventHandleBase):
    
    '''a client for chatting'''

    def __init__(self, server=None):
        PyShareEventHandleBase.__init__(self)
        #
        self.server = server
        self.add_listener(Evt_InstMsg_Received, self.handle_message)
        if server :
            self.server.services.chat.set_dispatcher(self.__msg_dispatcher)
        
        self.history_list = []
        
    def set_server(self, server):
        self.server = server
        self.server.services.chat.set_dispatcher(self.__msg_dispatcher)
    
    def __msg_dispatcher(self, msg):
        # simply put the message into msg_queue
        msg_inst = InstMessage.from_xml_string(msg)
        msg_inst.time_span = time.localtime()[:6]
        self.history_list.append(msg_inst)
        # return message to event catcher 
        post_event(Evt_InstMsg_Received(msg=msg_inst))
    
    def handle_message(self, evt):
        logger.debug('Not overloaded, the raw message is:%s' % evt.ret)

    def send(self, msg, to):
        if to == '*':
            self.send_to_all(msg)
        elif to != self.server.id :
            session = self.server.get_session(to)
            if not session :
                raise Exception('target %s dose not exist' % to)
            #
            # wrap it to a instant message object
            msg = InstMessage(msg, self.server.id, to)
            # send message to target
            try:
                session.remote_server.chat.receive(msg.to_xml())
            except Exception, why :
                logger.debug(str(why))
            # notify listener
            self.__msg_dispatcher(msg.to_xml())
        
    def send_to_all(self, msg):
        # wrap it to a instant message object
        msg = InstMessage(msg, self.server.id)
        # send to all
        for session in self.server.to_list() :
            if session.id != self.server.id:
                try:
                    session.remote_server.chat.receive(msg.to_xml())
                except Exception, why :
                    logger.debug(str(why))

        # notify listener
        self.__msg_dispatcher(msg.to_xml())
    
    
if __name__ == '__main__':
    
    import time
    class dummy :pass
    
    msg = InstMessage('hello', '112033', '112044')
    
    print msg
    print msg.sender
    print msg.to
    print msg.msg
    msg.msg = 'welcome!'
    print msg.msg
    
    xml = msg.to_xml()
    print xml
    
    msg2 = InstMessage.from_xml_string(xml)
    print msg2
    print msg2.msg
    
    chat = Chatting()
    chat.service = dummy()
    chat.service.chat = chat
    chat.id = 112033   
    
    
            